package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.annotation.AutoFill;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.entity.SetmealDish;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.result.PageResult;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Service
public class DishServiceImpl implements DishService {

    @Autowired
    private DishMapper dishMapper;

    @Autowired
    private DishFlavorMapper dishFlavorMapper;

    @Autowired
    private SetmealDishMapper setmealDishMapper;

    /**
     * 条件查询菜品和口味
     * @param dish
     * @return
     */
    public List<DishVO> listWithFlavor(Dish dish) {

        // 查询菜品
        List<Dish> dishList = dishMapper.list(dish);

        List<DishVO> dishVOList = new ArrayList<>();

        for (Dish d : dishList) {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(d,dishVO);

            //根据菜品id查询对应的口味
            List<DishFlavor> flavors = dishFlavorMapper.findByDishId(d.getId());

            dishVO.setFlavors(flavors);
            dishVOList.add(dishVO);
        }

        return dishVOList;
    }

    /**
     * {"code":"10086"}
     * 1. {"usrename":"admin","password":"123456"}
     * 2. 定义一个User类，但是必须有这两个属性在李米娜。7
     *  class User{
     *      String username;
     *      String password;
     *  }
     * public Result aaa(@RequestBody User u){}
     *
     *
     * localhost:8080/delete/3
     * @RequestMapping("/delete/{id}")
     * public Result delete(@PathVariable int id){
     *
     * }
     *
     *
     *
     * localhost:8080/delete?id=3
     * @RequestMapping("/delete")
     * public Result delete2(int id){
     *
     *
     * }
     *
     *
     * localhost:8080/addUser?username=admin&password=123
     * @RequestMappint("/addUser")
     * public Result add(String username, String password){
     *
     *
     * }
     *
     * localhost:8080/addUser?username=admin&password=123
     * @RequestMappint("/addUser")
     * public Result add(User user){
     *
     *
     * }
     *
     *
     *
     *
     *
     * 新增菜品
     *  1. 菜品数据包含菜品的基本数据 和 口味数据
     *  2. 菜品数据是保存在菜品表 （dish） , 口味数据是保存在口味表 (dish_flavor)
     *  3. 所以新增一道菜，就需要往两张表里面添加数据【和以前不一样了！】
     *      3.1 需要注入进来 dish表 对应 DishMapper
     *      3.2 需要注入进来 dish_flavor 对应 DishFlavorMapper
     *  4. 先调用谁？ 后调用谁 ?
     * @param dishDTO
     */
    @Override
    public void add(DishDTO dishDTO) {

        //1. 先调用菜品的dao ，完成菜品基础数据的新增工作
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO , dish);
        dishMapper.add(dish);


        //2. 再调用口味的dao, 完成口味的新增工作
        //2.1 从dto里面获取出来口味数据
        List<DishFlavor> flavorList = dishDTO.getFlavors();

        //2.2 判定，只有有口味数据的时候，才往表里面添加数据
        if( flavorList!=null && flavorList.size() > 0){

            //2.3 需要遍历集合，给每一个口味数据都设置它们的菜品ID，这样就知道这个口味数据是哪一道菜的数据了
            flavorList.forEach(dishFlavor -> {
                //需要添加菜品的时候，让mybatis返回菜品的主键ID
                dishFlavor.setDishId(dish.getId());
            });

            //2.4 调用dao添加口味数据
            dishFlavorMapper.add(flavorList);
        }
    }

    /**
     * 菜品分页
     *
     * @param dto
     * @return
     */
    @Override
    public PageResult page(DishPageQueryDTO dto) {

        //1. 设置查询第几页，每页多少条
        PageHelper.startPage(dto.getPage() , dto.getPageSize());

        //2. 调用dao
        Page<DishVO> page = dishMapper.page(dto);

        return new PageResult(page.getTotal() ,page.getResult());
    }

    /**
     * 批量删除菜品
     *  1. 可以删除一个菜品，也可以删除多个菜品
     *  2. 起售中的菜品不能删除
     *  3. 如果有套餐包含这道菜，那么也不能删除
     *  3. 除此之外都可以删除，但是除了要删除菜品的数据，也要删除口味的数据
     *
     * @param ids
     */
    @Override
    public void delete(List<Long> ids) {

        //1. 先看这里的菜品有没有属于起售的菜，如果有，禁止删除！  select * from dish where id  = 1
        ids.forEach(id->{
            //找到每一个菜
            Dish dish = dishMapper.findById(id);
            if(dish.getStatus() == StatusConstant.ENABLE){
                throw  new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
            }
        });


        //2. 再看这些菜有没有被套餐所包含着， 如果有，禁止删除！ select * from setmeal_dish  where dish_id  in (1,2,3);
        List<SetmealDish> setmealDishList = setmealDishMapper.findByDishId(ids);
        if(setmealDishList!=null && setmealDishList.size() > 0){
            // 如果进入了这里，那么表明这道菜品、其中的某一道菜品有被套餐包含着！
            throw  new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }

        //3. 来到这里，即表示可以删除菜品
        //3.1 删除菜品  delete from dish where id in (1,2,3)
        dishMapper.delete(ids);

        //3.2 删除口味数据  delete from dish_flavor where dish_id in (1,2,3)
        dishFlavorMapper.deleteByDishId(ids);
    }

    /**
     * 根据菜品ID查询菜品
     *  1. 菜品数据既要包含菜品也要包含口味
     *  2. 选择在service层使用 VO 来包装它们两个数据
     *  3. 这就要求一会要去查询两张表得到数据回来之后，再这里进行打包向上返回！
     *      3.1 查询菜品表，得到菜品数据
     *      3.2 查询口味表得到口味数据
     *
     * @param id
     * @return
     */
    @Override
    public DishVO findById(Long id) {

        //1. 根据菜品ID，查询菜品数据
        Dish dish = dishMapper.findById(id);

        //2. 根据菜品的ID，查询口味数据
        List<DishFlavor> flavorList = dishFlavorMapper.findByDishId(id);

        //3. 把这两个数据打包成一个DishVO
        DishVO dishVO = new DishVO();

        //3.1 拷贝dish数据到VO上面来
        BeanUtils.copyProperties(dish , dishVO);

        //3.2 设置进来口味的数据
        dishVO.setFlavors(flavorList);

        return dishVO;
    }

    /**
     * 更新菜品
     * 1. 更新菜品数据，有可能既要更新菜品表（dish） ，还需要更新口味表（dish_flavor）。
     * 2. 先往菜品表更新数据
     * 3. 更新口味表，不是按照一般的更新来做！
     *  3.1 因为要判定的东西太多了！口味是否是多了，是否是少了，是否是追加新的口味。
     *  3.2 可以先把原来的口味数据全部删除掉，然后把页面传递过来的口味数据添加到数据表里面即可！
     *
     * @param dto
     */
    @Override
    public void update(DishDTO dto) {

        //1. 更新菜品
        Dish dish = new Dish();
        BeanUtils.copyProperties(dto , dish);
        dishMapper.update(dish);

        //2. 先删除掉原来的口味数据
        dishFlavorMapper.deleteByDishId(Arrays.asList(dto.getId()));

        //3. 添加口味数据:: 如果页面传递过来的口味数据是没有的，那么就不用添加！
        if(dto.getFlavors() !=null && dto.getFlavors().size() > 0 ){

            //获取口味数据
            List<DishFlavor> flavorList  =  dto.getFlavors();

            //设置每一个口味属于哪一道菜
            flavorList.forEach(dishFlavor -> {
                dishFlavor.setDishId(dto.getId());
            });

            //批量添加
            dishFlavorMapper.add(flavorList);
        }

    }
}
